/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller.admin;

import cn.easyplatform.lang.Files;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.request.SimpleTextRequestMessage;
import cn.easyplatform.messages.request.vfs.ReadRequestMessage;
import cn.easyplatform.messages.vos.VfsVo;
import cn.easyplatform.spi.service.AdminService;
import cn.easyplatform.spi.service.VfsService;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.web.dialog.MessageBox;
import cn.easyplatform.web.service.ServiceLocator;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.OpenEvent;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zkmax.zul.Filedownload;
import org.zkoss.zul.*;

import java.util.Iterator;
import java.util.Stack;

/**
 * @Author: <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @Description:
 * @Since: 2.0.0 <br/>
 * @Date: Created in 2019/11/6 15:22
 * @Modified By:
 */
public class LogController extends SelectorComposer<Component> implements EventListener {

    @Wire("div#explorer")
    private Div explorer;

    @Wire("button#prev")
    private Button prev;

    @Wire("menupopup#mp")
    private Menupopup mp;

    @Wire("label#basePath")
    private Label basePath;

    private FastDateFormat format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");

    private Stack<String> stack = new Stack<>();

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        dir("");
        stack.add("");
    }

    private void dir(String dir) {
        prev.setDisabled(Strings.isBlank(dir));
        AdminService as = ServiceLocator.lookup(AdminService.class);
        IResponseMessage<?> resp = as.getLog(new SimpleRequestMessage(dir));
        explorer.getChildren().clear();
        if (resp.isSuccess()) {
            VfsVo[] vfs = (VfsVo[]) resp.getBody();
            if (Strings.isBlank(dir))
                basePath.setValue(FilenameUtils.getFullPath(vfs[0].getPath()));
            Div row = null;
            for (int i = 0; i < vfs.length; i++) {
                if (i % 4 == 0) {
                    row = new Div();
                    row.setZclass("row");
                    explorer.appendChild(row);
                }
                VfsVo f = vfs[i];
                Div col = new Div();
                col.setZclass("col-12 col-md-6 col-lg-3");
                if (f.isFolder()) {
                    A folder = new A();
                    folder.setZclass("d-flex text-decoration-none pt-3");
                    folder.setIconSclass("z-icon-folder text-warning h1");
                    Vlayout layout = new Vlayout();
                    layout.setSclass("ml-2");
                    layout.appendChild(new Label(f.getName()));
                    Label md = new Label(Labels.getLabel("admin.log.md", new Object[]{format.format(f.getModified())}));
                    md.setZclass("d-block text-truncate");
                    layout.appendChild(md);
                    layout.appendChild(new Label(Labels.getLabel("admin.log.size", new Object[]{f.getSize() / 1024})));
                    layout.setParent(folder);
                    folder.setAttribute("f", f);
                    folder.addEventListener(Events.ON_DOUBLE_CLICK, this);
                    folder.setContext(mp);
                    folder.setParent(col);
                } else {
                    A file = new A();
                    file.setZclass("d-flex text-decoration-none pt-3");
                    if (f.getName().endsWith("gz"))
                        file.setIconSclass("z-icon-file-zip-o h1");
                    else
                        file.setIconSclass("z-icon-file-o h1");
                    Vlayout layout = new Vlayout();
                    layout.setSclass("ml-2");
                    layout.appendChild(new Label(f.getName()));
                    Label md = new Label(Labels.getLabel("admin.log.md", new Object[]{format.format(f.getModified())}));
                    md.setZclass("d-block text-truncate");
                    layout.appendChild(md);
                    layout.appendChild(new Label(Labels.getLabel("admin.log.size", new Object[]{f.getSize() / 1024})));
                    layout.setParent(file);
                    file.setAttribute("f", f);
                    file.setContext(mp);
                    file.setParent(col);
                }
                col.setParent(row);
            }
        } else {
            MessageBox.showMessage(resp);
        }
    }

    @Override
    public void onEvent(Event event) throws Exception {
        VfsVo f = (VfsVo) event.getTarget().getAttribute("f");
        dir(f.getPath());
        stack.add(f.getPath());
    }

    @Listen("onOpen = #mp")
    public void onContext(OpenEvent oe) {
        if (oe.isOpen()) {
            oe.getTarget().setAttribute("f", oe.getReference().getAttribute("f"));
            VfsVo f = (VfsVo) oe.getTarget().getAttribute("f");
            oe.getTarget().getChildren().get(0).setVisible(f.isFolder());
            oe.getTarget().getChildren().get(1).setVisible(!f.isFolder());
        }
    }

    @Listen("onClick = menuitem")
    public void onMenuitem(Event evt) {
        VfsVo f = (VfsVo) evt.getTarget().getParent().getAttribute("f");
        int idx = evt.getTarget().getParent().getChildren().indexOf(evt.getTarget());
        if (f.isFolder()) {
            if (idx == 0) {//打开
                dir(f.getPath());
                stack.add(f.getPath());
            } else {//删除
                delete(f);
            }
        } else {
            if (idx == 1) {//下载
                VfsService vs = ServiceLocator.lookup(VfsService.class);
                IResponseMessage<?> resp = vs.read(new ReadRequestMessage(f.getPath()));
                if (resp.isSuccess()) {
                    byte[] data = (byte[]) resp.getBody();
                    Filedownload.save(data, Files.getContentType(FilenameUtils.getExtension(f.getName())), f.getName());
                } else
                    MessageBox.showMessage(resp);
            } else {//删除
                delete(f);
            }
        }
    }

    private void delete(VfsVo file) {
        Messagebox.show(Labels.getLabel("admin.service.op.confirm",
                new Object[]{Labels.getLabel("button.delete") + "'" + file.getName() + "'"}), Labels
                        .getLabel("admin.service.op.title"), Messagebox.CANCEL
                        | Messagebox.OK, Messagebox.QUESTION,
                new EventListener<Event>() {
                    @Override
                    public void onEvent(Event evt) throws Exception {
                        if (evt.getName().equals(Messagebox.ON_OK)) {
                            VfsService vs = ServiceLocator.lookup(VfsService.class);
                            IResponseMessage<?> resp = vs.delete(new SimpleTextRequestMessage(file.getPath()));
                            if (resp.isSuccess()) {
                                Iterator<Component> itr = explorer.queryAll("a").iterator();
                                while (itr.hasNext()) {
                                    Component c = itr.next();
                                    if (file == c.getAttribute("f")) {
                                        c.detach();
                                        dir(stack.peek());
                                        break;
                                    }
                                }
                            } else {
                                MessageBox.showMessage(Labels.getLabel("message.dialog.title.error"), Labels.getLabel("admin.log.delte.fail"));
                            }
                        }
                    }
                });
    }

    @Listen("onClick = #prev")
    public void onPrev() {
        stack.pop();
        dir(stack.peek());
    }

    @Listen("onClick = #refresh")
    public void onRefresh() {
        dir(stack.peek());
    }

}
